import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;


public class Main {
	static Connection connection = null;
	static Connection connectionTunned = null;
	static String driverName ="oracle.jdbc.driver.OracleDriver";
	static String serverName = "oraclefib.fib.upc.es";
	static String portNumber = "1521";
	static String sid = "ORABD";
	static String url="jdbc:oracle:thin:@"+serverName+":"+ portNumber+":"+sid;
	static String username = "jose.luis.orta";
	static String password = "DB231085";
	static String usernameTunned = "marc.baro.cusso";
	static String passwordTunned = "DB010689";
	static final int CONTEXT_ORACLE = 1;
	static final int CONTEXT_ORACLETUNNED = 2;
	static final int CONTEXT_MONGODB = 3;
	static final String MONGO_NORMAL_DBNAME = "cbde";
	
	public Main() {}
	
	public static  boolean connect(){
		try {
			Class.forName(driverName);
			DriverManager.setLoginTimeout(10);
			connection = DriverManager.getConnection(url, username, password);
			connectionTunned = DriverManager.getConnection(url, usernameTunned, passwordTunned);
		} catch (ClassNotFoundException e) {
			System.out.println("ClassNotFoundException : "+e.getMessage());
			return false;
		} catch (SQLException e) {
			System.out.println(e.getMessage());
			return false;
		}
		return true;
	}
	
	
	
	public static  boolean disconnect() {
		try {
			connection.close();
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	
	
	public static char menuOption() {
		char option = 'z';
			while (option == 'z') {
			System.out.println("Selecciona una opcion:");
			System.out.println("q: Salir");
			System.out.println("d: Borrar datos");
			System.out.println("i: Insertar 20.000 lineitems");
			System.out.println("g: Obtener datos existentes para consultas");
			System.out.println("1: Ejecutar query 1");
			System.out.println("2: Ejecutar query 2");
			System.out.println("3: Ejecutar query 3");
			System.out.println("4: Ejecutar query 4");
			System.out.print("Opcion:");
			try {
				option = new BufferedReader(new InputStreamReader(System.in)).readLine().charAt(0);
			} catch (Exception ex) {
				System.out.println("Opcion incorrecta");
				option = 'z';
			}
		}
		return option;
	}
	
	public static int askContext() {
		int nContext = -1;
		while (nContext == -1) {
			System.out.print("Escoje contexto (1: Oracle / 2: Oracle Tunneado/ 3: MongoDB):");
			try {
				nContext = Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());
			} catch (Exception ex) {
				System.out.println("Opcion Invalida");
				nContext = -1;
			}
		}
		return nContext;
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		char cOption;
		Template template = null;
		System.out.println("Conexion con Oracle: " +connect());
		
		int nContext = askContext();
		Map<String, Object> options = new HashMap<String,Object>();
		switch (nContext) {
			case CONTEXT_ORACLE:
				template = new OracleNormalTemplate();
				options.put("connection", connection);
				template.configure(options);
			break;
			case CONTEXT_ORACLETUNNED:
				template = new OracleTunnedTemplate();
				options.put("connection", connectionTunned);
				template.configure(options);
			break;
			case CONTEXT_MONGODB:
				template = new MongoNormalTemplate();
				options.put("db_name", MONGO_NORMAL_DBNAME);
				//TODO: Pasar los parametros necesarios
				template.configure(options);
			break;
		}
		while ((cOption = menuOption()) != 'q'){
			System.out.println("--------------------------------------");
			long previousTime = System.currentTimeMillis();
			switch (cOption) {
				case 'd':
					System.out.println("Estas seguro? Mira que luego le das y la lias.");
					try {
						char confirmation = new BufferedReader(new InputStreamReader(System.in)).readLine().charAt(0);
						if(Character.toLowerCase(confirmation) == 'y'
								|| Character.toLowerCase(confirmation) == 's') 
							System.out.println(template.deleteData() + " tablas limpiadas");
						else System.out.println("Pues deja de tocar botones.");
					} catch (Exception e1) {
						System.out.println("Todo ha petado catastroficamente: " + e1.getMessage());
					}
				break;
				case 'i':
					try {
						Map<String, Object> result = template.insertLineItems(20000);
						for (String table : template.tables) {
						System.out.println("Registros insertados en "+table+": " 
								+ result.get(table+"Regs") 
								+ "/" + result.get(table+"Expected"));
						}

					} catch (SQLException e) {
						// TODO Auto-generated catch block
						System.out.println("Se ha producido un error: " + e.getMessage());
					}
				break;
				case '1':
					System.out.println(template.query1() + " registros obtenidos");
				break;
				case '2':
					System.out.println(template.query2() + " registros obtenidos");
				break;
				case '3':
					System.out.println(template.query3() + " registros obtenidos");
				break;
				case '4':
					System.out.println(template.query4() + " registros obtenidos");
				break;
				case 'g':
				try {
					template.getDataForQueries();
				} catch (SQLException e) {
					System.out.println("Fallo al obtener datos: " + e.getMessage());
					e.printStackTrace();
				}
					break;
			}
			long currTime = System.currentTimeMillis();
			System.out.println("Elapsed time: " + (currTime - previousTime) + "ms");
			System.out.println("--------------------------------------");
		}
		disconnect();
	}

}
